package cn.schoolwow.flow.monitor.module.initial.flow;

import cn.schoolwow.ams.domain.option.QuickAMSOption;
import cn.schoolwow.flow.monitor.domain.FlowMonitorOption;
import cn.schoolwow.flow.monitor.entity.FlowLog;
import cn.schoolwow.flow.monitor.util.FlowMonitorUtil;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.domain.FlowDataFeature;
import cn.schoolwow.quickflow.dto.FlowContextDataRange;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import java.time.LocalDateTime;
import java.util.Map;

public class InsertFlowLogFlow implements BusinessFlow {
    private Logger logger = LoggerFactory.getLogger(InsertFlowLogFlow.class);

    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        setFlowLog(flowContext);
        setCategory(flowContext);
        insertFlowLog(flowContext);
    }

    @Override
    public String name() {
        return "流程开始时插入流程日志对象";
    }

    private void setFlowLog(FlowContext flowContext){
        FlowLog flowLog = new FlowLog();
        flowLog.setFlowId(flowContext.getId());
        flowLog.setName(flowContext.getFlowName());
        try {
            //保存请求数据
            {
                Map<String,Object> requestDataMap = flowContext.getRequestDataMap();
                flowLog.setRequestData(JSON.parseObject(JSON.toJSONString(requestDataMap, SerializerFeature.WriteClassName)));
            }
            //保存流程全局数据
            {
                Map<String,Object> contextDataMap = flowContext.getContextDataMap();
                flowLog.setQuickFlowData(JSON.parseObject(JSON.toJSONString(contextDataMap)));
            }
            //保存流程配置数据
            {
                Map<String,Object> flowConfigDataMap = flowContext.getFlowConfigDataMap();
                flowLog.setFlowConfigData(JSON.parseObject(JSON.toJSONString(flowConfigDataMap)));
            }
        }catch (Exception e){
            logger.error(e.getMessage(), e);
            flowContext.printFlowDataRange();
            flowLog.setException(FlowMonitorUtil.exception2String(e));
            flowLog.setExceptionMessage(e.getMessage());
        }

        flowLog.setFlowNameList(flowContext.getFlowArray().toJSONString());
        flowLog.setStartTime(LocalDateTime.now());
        flowContext.putInstanceData(flowLog, FlowContextDataRange.Flow, FlowDataFeature.TemporaryData);
    }

    private void setCategory(FlowContext flowContext){
        FlowLog flowLog = flowContext.checkInstanceData(FlowLog.class);
        ApplicationContext applicationContext = flowContext.checkInstanceData(ApplicationContext.class);
        QuickAMSOption quickAMSOption = applicationContext.getBean(QuickAMSOption.class);

        flowLog.setCategoryName("其他");
        if(flowContext.getFlowExecutorConfig().flowList.isEmpty()){
            return;
        }
        BusinessFlow businessFlow = flowContext.getFlowExecutorConfig().flowList.get(0);
        String className = businessFlow.getClass().getName();

        for(Map.Entry<String,String> entry:quickAMSOption.packageNameLabelMap.entrySet()){
            if(className.contains(entry.getKey())){
                flowLog.setCategoryName(entry.getValue());
            }
        }
    }

    private void insertFlowLog(FlowContext flowContext){
        FlowLog flowLog = flowContext.checkInstanceData(FlowLog.class);
        boolean shouldSaveFlowLog = flowContext.getData("是否保存流程日志",boolean.class,true);
        ApplicationContext applicationContext = flowContext.checkInstanceData(ApplicationContext.class);
        FlowMonitorOption flowMonitorOption = applicationContext.getBean(FlowMonitorOption.class);

        flowContext.putContextThreadLocalData("flowId", flowContext.getId());
        if(shouldSaveFlowLog){
            flowMonitorOption.dao.save(flowLog);
        }
        flowMonitorOption.dao.startRecord();
    }
}
